#include "mainwindow.h"

#include <QTimer>
#include <QProgressDialog>
#include <QToolBar>
#include <QStatusBar>
#include <QLabel>
#include <QSystemTrayIcon>

#include <core/config.h>
#include <core/coreconfig.h>
#include <core/sessionconfig.h>
#include <core/stitch.h>
#include <core/fileopenparameters.h>
#include "navigationmodemgr.h"
#include "viewarea.h"
#include "titletoolbar.h"
#include "toolbarhelper.h"
#include "statusbarhelper.h"
#include "systemtrayhelper.h"
using namespace stitch;

MainWindow::MainWindow(QWidget *p_parent)
    : FramelessMainWindowImpl(Config::getInst().getSessionConfig().getSystemTitleBarEnabled(), p_parent),
      m_dockWidgetHelper(this)
{
    Stitch::getInst().setMainWindow(this);
    NavigationModeMgr::init(this);

    setupUI();
    setupShortcuts();

    m_dockWidgetHelper.postSetup();

    // The signal is particularly useful if your application has to do some last-second cleanup.
    // Note that no user interaction is possible in this state.
    connect(qApp, &QCoreApplication::aboutToQuit,
            this, &MainWindow::closeOnQuit);

    //    connect(&Stitch::getInst(), &Stitch::exportRequested,
    //            this, &MainWindow::exportNotes);
}

void MainWindow::kickOffOnStart(const QStringList &p_paths)
{
    QTimer::singleShot(300, [this, p_paths]()
                       {
                           Q_UNUSED(p_paths);
                           QProgressDialog proDlg(tr("Initializing core components..."),
                                                  QString(),
                                                  0,
                                                  0,
                                                  this);
                       });
}

void MainWindow::quitApp()
{
    m_requestQuit = 0;
    close();
}

void MainWindow::showMainWindow()
{
    if (isMinimized())
    {
        if (m_windowOldState & Qt::WindowMaximized)
        {
            showMaximized();
        }
        else if (m_windowOldState & Qt::WindowFullScreen)
        {
            showFullScreen();
        }
        else
        {
            showNormal();
        }
    }
    else
    {
        show();
        // Need to call raise() in macOS.
        raise();
    }

    activateWindow();
}

void MainWindow::openFiles(const QStringList &p_files)
{
    for (const auto &file : p_files)
    {
        emit Stitch::getInst().openFileRequested(file, QSharedPointer<FileOpenParameters>::create());
    }
}

void MainWindow::setStayOnTop(bool p_enabled)
{
    bool shown = isVisible();
    Qt::WindowFlags flags = windowFlags();

    const Qt::WindowFlags magicFlag = Qt::WindowStaysOnTopHint;
    if (p_enabled) {
        setWindowFlags(flags | magicFlag);
    } else {
        setWindowFlags(flags ^ magicFlag);
    }

    if (shown) {
        show();
    }
}
void MainWindow::setupUI()
{
    setupCentralWidget();
    setupDocks();
    setupToolBar();
    setupStatusBar();
    setupTipsArea();
    setupSystemTray();
    //m_dockWidgetHelper.activateDock(DockWidgetHelper::NavigationDock);
}

void MainWindow::setupShortcuts()
{

}

void MainWindow::setupCentralWidget()
{
    m_viewArea = new ViewArea(this);
    NavigationModeMgr::getInst().registerNavigationTarget(m_viewArea);
    //    connect(&Stitch::getInst().getBufferMgr(), &BufferMgr::bufferRequested,
    //            m_viewArea, &ViewArea::openBuffer);

    //    connect(m_viewArea, &ViewArea::statusWidgetChanged,
    //            this, [this](QWidget *p_widget) {
    //                if (m_viewAreaStatusWidget) {
    //                    // Will hide it.
    //                    statusBar()->removeWidget(m_viewAreaStatusWidget);
    //                }

    //                m_viewAreaStatusWidget = p_widget;
    //                if (m_viewAreaStatusWidget) {
    //                    statusBar()->addPermanentWidget(m_viewAreaStatusWidget);
    //                    m_viewAreaStatusWidget->show();
    //                }
    //            });
    //    connect(m_viewArea, &ViewArea::currentViewWindowChanged,
    //            this, [this]() {
    //                setWindowTitle(getViewAreaTitle());
    //            });
    //    connect(m_viewArea, &ViewArea::currentViewWindowUpdated,
    //            this, [this]() {
    //                setWindowTitle(getViewAreaTitle());
    //            });

    //    {
    //        auto &notebookMgr = Stitch::getInst().getNotebookMgr();
    //        connect(&notebookMgr, &NotebookMgr::notebookAboutToClose,
    //                this, [this](const Notebook *p_notebook) {
    //                    m_viewArea->close(p_notebook, true);
    //                });
    //        connect(&notebookMgr, &NotebookMgr::notebookAboutToRemove,
    //                this, [this](const Notebook *p_notebook) {
    //                    m_viewArea->close(p_notebook, true);
    //                });
    //    }

    setCentralWidget(m_viewArea);
}

void MainWindow::setupDocks()
{

    setupNotebookExplorer();

    setupTagExplorer();

    setupOutlineViewer();

    setupConsoleViewer();

    setupHistoryPanel();

    setupSearchPanel();

    setupSnippetPanel();

    setupLocationList();

    //m_dockWidgetHelper.setupDocks();

    //NavigationModeMgr::getInst().registerNavigationTarget(&m_dockWidgetHelper);
}

void MainWindow::setupToolBar()
{
    const int sz = Config::getInst().getCoreConfig().getToolBarIconSize();

    if (isFrameless())
    {
        auto toolBar = new TitleToolBar(tr("Global"), this);
        toolBar->setIconSize(QSize(sz + 4, sz + 4));
        ToolBarHelper::setupToolBars(this, toolBar);
        toolBar->addTitleBarIcons(ToolBarHelper::generateIcon(QStringLiteral("minimize.svg")),
                                  ToolBarHelper::generateIcon(QStringLiteral("maximize.svg")),
                                  ToolBarHelper::generateIcon(QStringLiteral("maximize_restore.svg")),
                                  ToolBarHelper::generateDangerousIcon(QStringLiteral("close.svg")));
        setTitleBar(toolBar);
        connect(this, &FramelessMainWindowImpl::windowStateChanged,
                toolBar, &TitleToolBar::updateMaximizeAct);
    }
    else
    {
        auto toolBar = new QToolBar(tr("Global"), this);
        toolBar->setIconSize(QSize(sz, sz));
        ToolBarHelper::setupToolBars(this, toolBar);
    }

    // Disable the context menu above tool bar.
    setContextMenuPolicy(Qt::NoContextMenu);
}

void MainWindow::setupStatusBar()
{
    StatusBarHelper::setupStatusBar(this);
    connect(&Stitch::getInst(), &Stitch::statusMessageRequested,
            statusBar(), &QStatusBar::showMessage);
}

void MainWindow::setupTipsArea()
{
    connect(&Stitch::getInst(), &Stitch::tipsRequested,
            this, &MainWindow::showTips);
}

void MainWindow::setupSystemTray()
{
    m_trayIcon = SystemTrayHelper::setupSystemTray(this);
    m_trayIcon->show();
}

void MainWindow::setupOutlineViewer()
{
}

void MainWindow::setupConsoleViewer()
{
}

void MainWindow::setupSearchPanel()
{
}

void MainWindow::setupLocationList()
{
}

void MainWindow::setupSnippetPanel()
{
}

void MainWindow::setupHistoryPanel()
{
}

void MainWindow::setupNotebookExplorer()
{
}

void MainWindow::setupTagExplorer()
{
}

void MainWindow::createTipsArea()
{
    if (m_tipsLabel) {
        return;
    }

    m_tipsLabel = new QLabel(this);
    m_tipsLabel->setObjectName("MainWindowTipsLabel");
    m_tipsLabel->hide();

    m_tipsTimer = new QTimer(this);
    m_tipsTimer->setSingleShot(true);
    m_tipsTimer->setInterval(3000);
    connect(m_tipsTimer, &QTimer::timeout,
            this, [this]() {
                setTipsAreaVisible(false);
            });
}

void MainWindow::setTipsAreaVisible(bool p_visible)
{
    Q_ASSERT(m_tipsLabel);
    if (p_visible) {
        m_tipsLabel->adjustSize();
        int labelW = m_tipsLabel->width();
        int labelH = m_tipsLabel->height();
        int x = (width() - labelW) / 2;
        int y = (height() - labelH) / 3;
        if (x < 0) {
            x = 0;
        }
        if (y < 0) {
            y = 0;
        }

        m_tipsLabel->move(x, y);
        m_tipsLabel->show();
    } else {
        m_tipsLabel->hide();
    }
}

void MainWindow::closeOnQuit()
{
    // No user interaction is available.
    emit mainWindowClosedOnQuit();

    // Stitch::getInst().getNotebookMgr().close();
}

void MainWindow::showTips(const QString &p_message, int p_timeoutMilliseconds)
{
    createTipsArea();

    m_tipsTimer->stop();

    setTipsAreaVisible(false);

    if (p_message.isEmpty()) {
        return;
    }

    m_tipsLabel->setText(p_message);
    setTipsAreaVisible(true);

    m_tipsTimer->start(p_timeoutMilliseconds);
}

MainWindow::~MainWindow()
{
    // Should be desturcted before status bar.
    delete m_viewArea;
    m_viewArea = nullptr;
}
